
#include <iostream>
#include <memory>
#include <ctime>
#include <string>
#include <vector>
using namespace std;
#include <pthread.h>
#include "blockQueue.hpp"
#include "Task.hpp"
using namespace blockqueue;
#include <unistd.h>

/*我们为了区分每个线程的名称
 *所以构造一个结构体*/
template <class T>
struct blockQueues
{
    blockQueue<T> *bq;
    blockQueue<filelogTask> *fbq;
    pthread_t tid;
    string name;
};

/*消费者就是从阻塞队列当中拿数据*/
void *consumerDemo(void *args)
{
    blockQueues<culculateTask<int>> *bqs = static_cast<blockQueues<culculateTask<int>> *>(args);

    while (true)
    {
        culculateTask<int> data;
        bqs->bq->pop(&data);
        cout << bqs->name << "consumed a task: ";
        string ret = data();
        filelogTask save(ret); /*函数返回值作为sava的构造函数的参数*/
        bqs->fbq->push(save);
        cout << bqs->name << "producted a data: " << ret << endl;
        sleep(1); /*让消费者消费的稍微慢一些*/
    }
    pthread_exit(nullptr);
}

/*生产者就是向阻塞队列当中写数据*/
void *productorDemo(void *args)
{
    blockQueues<culculateTask<int>> *bqs = static_cast<blockQueues<culculateTask<int>> *>(args);

    while (true)
    {
        int left = rand() % 100;
        int right = rand() % 200;
        char oper[5] = {'+', '-', '*', '/', '%'};
        culculateTask<int> task(left, right, oper[rand() % sizeof(oper)]);
        bqs->bq->push(task);
        cout << bqs->name << "producted a task: " << task.getTaskName() << endl;
    }
    pthread_exit(nullptr);
}

void *saverDemo(void *args)
{
    blockQueues<culculateTask<int>> *bqs = static_cast<blockQueues<culculateTask<int>> *>(args);

    while (true)
    {
        filelogTask save;
        bqs->fbq->pop(&save);
        save();
        cout << bqs->name << "save data success" << endl;
    }
}

int main()
{
    srand((unsigned int)time(nullptr));

    vector<blockQueues<culculateTask<int>> *> vec;

    /*calculateTask类现在要负责整数之间的运算*/
    blockQueue<culculateTask<int>> *bq = new blockQueue<culculateTask<int>>();
    blockQueue<filelogTask> *fbq = new blockQueue<filelogTask>();

    for (int i = 0; i < 4; i++)
    { /*生产者线程*/
        pthread_t productor;
        blockQueues<culculateTask<int>> *bqs = new blockQueues<culculateTask<int>>();
        bqs->bq = bq;
        bqs->fbq = fbq;
        bqs->name = "productor:" + to_string(i + 1);
        pthread_create(&productor, nullptr, productorDemo, bqs);
        bqs->tid = productor;
        vec.push_back(bqs);
    }

    for (int i = 0; i < 4; i++)
    { /*消费者线程*/
        pthread_t consumer;
        blockQueues<culculateTask<int>> *bqs = new blockQueues<culculateTask<int>>();
        bqs->bq = bq;
        bqs->fbq = fbq;
        bqs->name = "consumer:" + to_string(i + 1);
        pthread_create(&consumer, nullptr, consumerDemo, bqs);
        bqs->tid = consumer;
        vec.push_back(bqs);
    }

    for (int i = 0; i < 4; i++)
    { /*日志线程*/
        pthread_t saver;
        blockQueues<culculateTask<int>> *bqs = new blockQueues<culculateTask<int>>();
        bqs->bq = bq;
        bqs->fbq = fbq;
        bqs->name = "saver:" + to_string(i + 1);
        pthread_create(&saver, nullptr, saverDemo, bqs);
        bqs->tid = saver;
        vec.push_back(bqs);
    }

    for (auto &e : vec)
    {
        pthread_join(e->tid, nullptr);
    }

    return 0;
}

// /*因为中间的消费者/生产者要存取两个阻塞队列
//  *所以构造一个结构体*/
// template <class T>
// struct blockQueues
// {
//     blockQueue<T> *bq;
//     blockQueue<filelogTask> *fbq;
// };

// /*消费者就是从阻塞队列当中拿数据*/
// void *consumerDemo(void *args)
// {
//     blockQueue<culculateTask<int>> *bq = (static_cast<blockQueues<culculateTask<int>> *>(args))->bq;
//     blockQueue<filelogTask> *fbq = (static_cast<blockQueues<culculateTask<int>> *>(args))->fbq;

//     while (true)
//     {
//         culculateTask<int> data;
//         bq->pop(&data);
//         cout << "consumer consumed a task: ";
//         string ret = data();
//         filelogTask save(ret);/*函数返回值作为sava的构造函数的参数*/
//         fbq->push(save);
//         cout << "consumer producted a data: " << ret << endl;
//         sleep(1);/*让消费者消费的稍微慢一些*/
//     }
//     pthread_exit(nullptr);
// }

// /*生产者就是向阻塞队列当中写数据*/
// void *productorDemo(void *args)
// {
//    blockQueue<culculateTask<int>> *bq = static_cast<blockQueue<culculateTask<int>> *>(args);

//     while (true)
//     {
//         int left = rand() % 100;
//         int right = rand() % 200;
//         char oper[5] = {'+','-','*','/','%'};
//         culculateTask<int> task(left,right,oper[rand() % sizeof(oper)]);
//         bq->push(task);
//         cout << "productor producted a task: " << task.getTaskName() << endl;
//     }
//     pthread_exit(nullptr);
// }

// void *saverDemo(void *args)
// {
//     blockQueue<filelogTask> *fbq = static_cast<blockQueue<filelogTask> *>(args);
//     while(true)
//     {
//         filelogTask save;
//         fbq->pop(&save);
//         save();
//         cout << "saver save data success" << endl;
//     }

// }

// int main()
// {
//     srand((unsigned int)time(nullptr));

//     /*calculateTask类现在要负责整数之间的运算*/
//     blockQueue<culculateTask<int>> *bq = new blockQueue<culculateTask<int>>();
//     blockQueue<filelogTask> *fbq = new blockQueue<filelogTask>();
//     blockQueues<culculateTask<int>> *bqs = new blockQueues<culculateTask<int>>();
//     bqs->bq = bq;
//     bqs->fbq = fbq;

//     pthread_t productor,consumer,saver;
//     pthread_create(&productor,nullptr,productorDemo,bq);
//     pthread_create(&consumer,nullptr,consumerDemo,bqs);
//     pthread_create(&saver,nullptr,saverDemo,fbq);

//     pthread_join(productor,nullptr);
//     pthread_join(consumer,nullptr);
//     pthread_join(saver,nullptr);

//     return 0;
// }

// /*消费者就是从阻塞队列当中拿数据*/
// void *consumerDemo(void *args)
// {
//     blockQueue<culculateTask<int>> *bq = static_cast<blockQueue<culculateTask<int>> *>(args);
//     while (true)
//     {
//         culculateTask<int> data;
//         bq->pop(&data);
//         cout << "consumer consumed a task: ";
//         data();
//         sleep(1);/*让消费者消费的稍微慢一些*/
//     }
//     pthread_exit(nullptr);
// }

// /*生产者就是向阻塞队列当中写数据*/
// void *productorDemo(void *args)
// {
//    blockQueue<culculateTask<int>> *bq = static_cast<blockQueue<culculateTask<int>> *>(args);

//     while (true)
//     {
//         int left = rand() % 100;
//         int right = rand() % 200;
//         char oper[5] = {'+','-','*','/','%'};
//         culculateTask<int> task(left,right,oper[rand() % sizeof(oper)]);
//         bq->push(task);
//         cout << "productor producted a task: " << task.getTaskName() << endl;
//     }
//     pthread_exit(nullptr);
// }

// int main()
// {
//     srand((unsigned int)time(nullptr));

//     /*calculateTask类现在要负责整数之间的运算*/
//     blockQueue<culculateTask<int>> *bq = new blockQueue<culculateTask<int>>();

//     pthread_t productor,consumer;
//     pthread_create(&productor,nullptr,productorDemo,bq);
//     pthread_create(&consumer,nullptr,consumerDemo,bq);

//     pthread_join(productor,nullptr);
//     pthread_join(consumer,nullptr);
//     return 0;
// }

// /*消费者就是从阻塞队列当中拿数据*/
// void *consumerDemo(void *args)
// {
//     blockQueue<int> *bq = static_cast<blockQueue<int> *>(args);
//     while (true)
//     {
//         int data;
//         bq->pop(&data);
//         cout << "consumer consumed a data: " << data << endl;
//         sleep(1);/*让消费者消费的稍微慢一些*/
//     }
//     pthread_exit(nullptr);
// }

// /*生产者就是向阻塞队列当中写数据*/
// void *productorDemo(void *args)
// {
//    blockQueue<int> *bq = static_cast<blockQueue<int> *>(args);

//     while (true)
//     {
//         int data = rand() % 100;
//         bq->push(data);
//         cout << "productor producted a data: " << data << endl;
//     }
//     pthread_exit(nullptr);
// }

// int main()
// {
//     srand((unsigned int)time(nullptr));
//     blockQueue<int> *bq = new blockQueue<int>();

//     pthread_t productor,consumer;
//     pthread_create(&productor,nullptr,productorDemo,bq);
//     pthread_create(&consumer,nullptr,consumerDemo,bq);

//     pthread_join(productor,nullptr);
//     pthread_join(consumer,nullptr);
//     return 0;
// }